Skip to content

一、概述

jar包被其他人拿走很容易编译出源代码,造成源代码泄露,影响程序安全。

参考地址:

1.1 常见的加密工具

XJar

Spring Boot JAR 安全加密运行工具,同时支持的原生JAR。 基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译

功能特性: 无需侵入代码,只需要把编译好的JAR包通过工具加密即可。 完全内存解密,杜绝源码以及字节码泄露或反编译。 支持所有JDK内置加解密算法。 可选择需要加解密的字节码或其他资源文件,避免计算资源浪费。

运行环境: 新版XJar只支持go启动器模式启动加密后的jar包 , 加密后需要go环境生成go启动器 . 运行时不需要go环境。

加密原理: 对jar的字节码加密 , 启动jar包时调用自定义的类加载器, 重写findClass方法,拿到字节流后,先解密再调Classloader的defineClass方法,初始化成Class对象。

加密结果: 加密后的Class不能反编译。

ProGuard

ProGuard 是一个免费的 Java 类文件的压缩,优化,混淆器。它删除没有用的类,字段,方法与属性。使字节码最大程度地优化,使用简短且无意义的名字来重命名类、字段和方法 。

功能特性: 1、压缩(shrink) 移除未使用的类、方法、字段等; 2、优化(optimize)优化字节码、简化代码等操作; 3、混淆(obfuscate)使用简短的、无意义的名称重全名类名、方法名、字段等; 4、预校验(preverify)为class添加预校验信息。

运行环境: jdk,不需要额外运行环境。

加密结果: 混淆后的class反编译后都是一些魔法命名字符,增加阅读难度。

ClassFinal

ClassFinal 是一款 Java class 文件安全加密工具,支持直接加密 jar 包或 war 包,无需修改任何项目代码,兼容 spring-framework,可避免源码泄漏或字节码被反编译。

项目模块说明: 1、classfinal-core: ClassFinalde 的核心模块,几乎所有加密的代码都在这里; 2、classfinal-fatjar: ClassFinal 打包成独立运行的 jar 包; 3、classfinal-maven-plugin: ClassFinal 加密的 maven 插件;

功能特性: 1、无需修改原项目代码,只要把编译好的 jar/war 包用本工具加密即可。 2、运行加密项目时,无需求修改 tomcat,spring 等源代码。 3、支持普通 jar 包、springboot jar 包以及普通 java web 项目编译的 war 包。 4、支持 spring framework、swagger 等需要在启动过程中扫描注解或生成字节码的框架。 5、支持 maven 插件,添加插件后在打包过程中自动加密。 6、支持加密 WEB-INF/lib 或 BOOT-INF/lib 下的依赖 jar 包。

环境依赖: JDK 1.8 +

本工具使用 AES 算法加密 class 文件,密码是保证不被破解的关键,请保存好密码,请勿泄漏。 密码一旦忘记,项目不可启动且无法恢复,请牢记密码。 本工具加密后,原始的 class 文件并不会完全被加密,只是方法体被清空,保留方法参数、注解等信息,这是为了兼容 spring,swagger 等扫描注解的框架; 方法体被清空后,反编译者只能看到方法名和注解,看不到方法的具体内容;当 class 被 classloader 加载时,真正的方法体会被解密注入。

加密结果: 配置文件反编译后为空

二、ClassFinal使用

1.1 打包后加密

使用ClassFinal的加密工具,直接将打包后的jar包进行加密。加密工具下载地址

启动参数说明

-file        加密的jar/war完整路径
-packages    加密的包名(可为空,多个用","分割)
-libjars     jar/war包lib下要加密jar文件名(可为空,多个用","分割)
-cfgfiles    需要加密的配置文件,一般是classes目录下的yml或properties文件(可为空,多个用","分割)
-exclude     排除的类名(可为空,多个用","分割)
-classpath   外部依赖的jar目录,例如/tomcat/lib(可为空,多个用","分割)
-pwd         加密密码,如果是#号,则使用无密码模式加密
-code        机器码,在绑定的机器生成,加密后只可在此机器上运行
-Y          无需确认,不加此参数会提示确认以上信息

执行命令示例

bat
java -jar classfinal-fatjar-1.2.1.jar -file yourpaoject.jar -libjars a.jar,b.jar -packages com.yourpackage,com.yourpackage2 -exclude com.yourpackage.Main -pwd 123456 -Y

执行后会在jar包的路径下生成一个 jar包名+encrypted.jar的文件

1.2 maven打包加密

maven打包加密是在打包后,为打包后的包再进行一次加密。因此,插件需要放置到打包的插件后边。

方式1:插件方式

xml
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <!--
                1. 加密后,方法体被清空,保留方法参数、注解等信息.主要兼容swagger文档注解扫描
                2. 方法体被清空后,反编译只能看到方法名和注解,看不到方法体的具体内容
                3. 加密后的项目需要设置javaagent来启动,启动过程中解密class,完全内存解密,不留下任何解密后的文件
                4. 启动加密后的jar,生成xxx-encrypted.jar,这个就是加密后的jar文件,加密后不可直接执行
                5. 无密码启动方式,java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar
                6. 有密码启动方式,java -javaagent:xxx-encrypted.jar='-pwd= 密码' -jar xxx-encrypted.jar
            -->
            <groupId>net.roseboy</groupId>
            <artifactId>classfinal-maven-plugin</artifactId>
            <version>1.2.1</version>
            <configuration>
                <password>#</password><!-- #表示启动时不需要密码,事实上对于代码混淆来说,这个密码没什么用,它只是一个启动密码 -->
                <excludes>org.spring</excludes>
                <packages>${groupId}</packages><!-- 加密的包名,多个包用逗号分开 -->
                <cfgfiles>application.yml,application-dev.yml</cfgfiles><!-- 加密的配置文件,多个包用逗号分开 -->
                <libjars>hutool-all.jar</libjars> <!-- jar包lib下面要加密的jar依赖文件,多个包用逗号分开 -->
                <code>xxxx</code> <!-- 指定机器启动,机器码 -->
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>classFinal</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

</build>

方式2:插件执行命令方式

该方式原理是使用1.1的方式,将1.1的命令写成脚本,然后再生成jar包后,再对jar包进行加密。

需要将1.1的工具包 和脚本文件放置到项目根目录。

脚本文件:

bat
java -jar classfinal-fatjar-1.2.1.jar -file yourpaoject.jar -libjars a.jar,b.jar -packages com.yourpackage,com.yourpackage2 -exclude com.yourpackage.Main -pwd 123456 -Y

插件配置:(粘贴在打包插件后

xml
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.2.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>exec</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <executable>classfinal.bat</executable>
    </configuration>
</plugin>

1.3 jar包启动

加密后一般是后会在jar包的路径下生成一个 jar包名+encrypted.jar的文件

启动命令:

sh
#无密码启动

java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar

# 有密码启动


<NolebasePageProperties />





java -javaagent:xxx-encrypted.jar='-pwd=密码' -jar xxx-encrypted.jar

1.4 绑定机器码

使用1.1的工具包,执行命令生成机器码:

sh
java -jar classfinal-fatjar-1.2.1.jar -C